use core::str;
use std::mem;

use bytes::{Bytes, BytesMut};
use header::{header_items::Headers, names::HeaderName, values::HeaderValue};
use title::{Method, RequestTitle, Response, Title, Version};
use tools::{
	error::buf_err::ToBufError,
	types::bufs::{FromBuf, ToBuf},
};

use crate::{
	untils::url::SipURI, SIP_URL_PREFIX, SIP_URL_PREFIX_PARENTHESIS, SIP_URL_SUFFIX_PARENTHESIS,
};

pub(crate) mod header;
pub mod title;

///代表一个数据帧
#[derive(Debug)]
pub struct Frame {
	//这里存放对应的二进制数据,目前只有解码的时候这里存放了数据.
	data: Bytes,
	headers: Headers,
	body: Bytes,
	title: Title,
	//当生成数据时,需要一个存放位置,以保存StrPrt指针指向的数据..
	//只写不读,因此前缀加一个'_'
	_temp_data: String,
}

impl Default for Frame {
	fn default() -> Self {
		Self {
			data: Default::default(),
			headers: Default::default(),
			body: Default::default(),
			title: Default::default(),
			_temp_data: Default::default(),
		}
	}
}

impl Frame {
	#[inline]
	pub fn add_header<T>(&mut self, name: HeaderName, value: T)
	where
		T: Into<HeaderValue>,
	{
		self.headers.insert(name, value.into());
	}

	#[inline]
	pub fn set_body(&mut self, body: Bytes) {
		self.body = body;
	}
	///返回一个新的请求数据..一个新的请求必定是INVITE请求
	pub fn invite(to: &str) -> Self {
		let mut temp_data = String::with_capacity(50);
		unsafe {
			temp_data.push_str(mem::transmute(SIP_URL_PREFIX_PARENTHESIS));
			temp_data.push_str(mem::transmute(SIP_URL_PREFIX));
			temp_data.push_str(to);
			temp_data.push_str(mem::transmute(SIP_URL_SUFFIX_PARENTHESIS));
		}

		let title_ptr = SipURI::from_str(&temp_data[..temp_data.len()]);
		Self {
			_temp_data: temp_data,
			title: Title::Request(RequestTitle::new(Version::V2_0, Method::Invite, title_ptr)),
			..Default::default()
		}
	}

	///返回一个100try的内容.因为100try就是根据inv的请求来的.所以可以直接返回
	///buf的作用是给一个统一的缓存...
	pub fn resp_try(res: &Frame, buf: &mut BytesMut) -> Self {
		Self {
			title: Title::with_resp_2(Response::Try),
			..Default::default()
		}
		//TODO 这里没有实现
	}

	///此方法返回当前数据对应的字节码...如果是从解码来的,直接返回对应的解码数据..
	pub fn into_bytes(mut self, target: &mut BytesMut) -> Result<Bytes, ToBufError> {
		//如果已经存在,则直接返回此数据
		if !self.data.is_empty() {
			return Ok(self.data);
		}

		if self.headers.is_empty() {
			return Err(ToBufError::new("sip消息不能没有头数据"));
		}

		self.title.write_to(target)?;
		if !self.body.is_empty() {
			self.headers.set_content_length(self.body.len());
		}

		self.headers.write_to(target)?;
		target.extend_from_slice(self.body());

		Ok(target.split().freeze())
	}

	pub fn body(&self) -> &Bytes {
		&self.body
	}

	pub fn data(&self) -> &Bytes {
		&self.data
	}

	pub fn headers(&self) -> &Headers {
		&self.headers
	}

	pub fn version(&self) -> Version {
		self.title.version()
	}
}

impl FromBuf for Frame {
	type From = Bytes;

	#[inline]
	fn from_buf_all(mut from: Self::From) -> Result<Self, tools::error::buf_err::FromBufError>
	where
		Self: Sized,
	{
		Self::from_buf(&mut from)
	}

	fn from_buf(from: &mut Self::From) -> Result<Self, tools::error::buf_err::FromBufError>
	where
		Self: Sized,
	{
		let data = from.clone();
		// 先处理标题
		let title = Title::from_buf(from)?;
		// 头信息
		let headers = Headers::from_buf(from)?;
		// 处理内容
		let body = from.clone();

		Ok(Self {
			data,
			headers,
			body,
			title,
			_temp_data: Default::default(),
			..Default::default()
		})
	}
}
